﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MelonLoader;
using Newtonsoft.Json.Linq;

namespace SultanModLoader
{
    public class ModJsonOption
    {

        /// <summary>
        /// 多级索引分隔符
        /// </summary>
        public static readonly string SEPARATOR = "$#";

        public const string Create = "create";
        public const string Replace = "replace";
        public const string Merge = "merge";
        

        public static readonly string[] _Options = { Create, Replace, Merge};
        public static IEnumerable<string> Options { get { return _Options.AsEnumerable(); } } 
        private ModJsonOption() { }



        public static void ApplyCreate(JObject targetJObject, JToken applyJToken, ConsoleColor color = ConsoleColor.White, int msgLevel = 0)
        {
            if (targetJObject == null || applyJToken == null) return;
            if (applyJToken.Type != JTokenType.Object)
            {
                AssetsTool.LevelMsg($"格式错误:{applyJToken.Type}非{JTokenType.Object}", msgLevel, ConsoleColor.Red);
                return;
            }
            JObject modToken = (JObject)applyJToken;
            // 遍历需要处理的Json
            foreach (var prop in modToken.Properties())
            {
                var ids = prop.Name;
                var value = prop.Value;
                try
                {
                    // 判断id是否合法
                    if (ids.Contains(SEPARATOR)) throw new MyException("不支持多级索引");
                    // 判断id是否已存在
                    if (targetJObject.ContainsKey(ids)) throw new MyException("ID已存在");
                    AssetsTool.LevelMsg($"{ids}", msgLevel, color);
                    targetJObject.Add(ids, value);
                }
                catch (MyException ex)
                {
                    AssetsTool.LevelMsg($"{ids} : {ex.Message}");
                }
                catch (Exception ex)
                {
                    MelonLogger.Error(ex.Message);
                }

            }
        }
        public static void ApplyReplace(JObject targetJObject, JToken applyJToken, ConsoleColor color = ConsoleColor.White, int msgLevel = 0)
        {
            if (targetJObject == null || applyJToken == null) return;
            if (applyJToken.Type != JTokenType.Object)
            {
                AssetsTool.LevelMsg($"格式错误:{applyJToken.Type}非{JTokenType.Object}", msgLevel, ConsoleColor.Red);
                return;
            }
            JObject modToken = (JObject)applyJToken;
            // 遍历需要处理的Json
            foreach (var prop in modToken.Properties())
            {
                var ids = prop.Name;
                var value = prop.Value;
                try
                {
                    // 查找对应的JToken
                    var (parentJToken, id) = FindJToken(targetJObject, ids, SEPARATOR);
                    // 为空则ID不存在
                    if (parentJToken == null) throw new MyException("ID不存在");
                    // 判断类型并合并
                    AssetsTool.LevelMsg($"{ids}", msgLevel, color);
                    parentJToken[id] = value;
                }
                catch (MyException ex)
                {
                    AssetsTool.LevelMsg($"{ids} : {ex.Message}");
                }
                catch (Exception ex)
                {
                    MelonLogger.Error(ex.Message);
                }

            }
        }

        public static void ApplyMerge(JObject targetJObject, JToken applyJToken, ConsoleColor color = ConsoleColor.White, int msgLevel = 0)
        {
            if (targetJObject == null || applyJToken == null) return;
            if (applyJToken.Type != JTokenType.Object)
            {
                AssetsTool.LevelMsg($"格式错误:{applyJToken.Type}非{JTokenType.Object}", msgLevel, ConsoleColor.Red);
                return;
            }
            JObject modToken = (JObject)applyJToken;
            // 遍历需要处理的Json
            foreach (var prop in modToken.Properties())
            {
                var ids = prop.Name;
                var value = prop.Value;
                try
                {
                    // 查找对应的JToken
                    var (parentJToken, id) = FindJToken(targetJObject, ids, SEPARATOR);
                    // 为空则ID不存在
                    if (parentJToken == null) throw new MyException("ID不存在");
                    // 判断类型并合并
                    var jToken = parentJToken[id];
                    switch (jToken.Type)
                    {
                        case JTokenType.Array:
                            ((JArray)jToken).Merge(value); break;
                        case JTokenType.Object:
                            ((JObject)jToken).Merge(value); break;
                        default:
                            throw new Exception($"类型非法{jToken.Type}");
                    }
                    AssetsTool.LevelMsg($"{ids}", msgLevel, color);
                }
                catch (MyException ex)
                {
                    AssetsTool.LevelMsg($"{ids} : {ex.Message}");
                }
                catch (Exception ex)
                {
                    MelonLogger.Error(ex.Message);
                }

            }
        }




        class MyException: Exception
        {
            public MyException() : base()
            {

            }
            public MyException(string message) : base(message)
            {
            }
        }

        

        /// <summary>
        /// 根据多级路径查找JToken
        /// </summary>
        /// <param name="obj">根JObject对象</param>
        /// <param name="ids">层级路径（示例：root#child#item）</param>
        /// <param name="separator">路径分隔符（默认$#）</param>
        /// <returns>包含父节点和目标键的元组</returns>
        /// <exception cref="MyException">包含中文错误信息的自定义异常</exception>
        private static (JToken, string) FindJToken(JObject obj, string ids, string separator)
        {
            // 使用完整分隔符进行分割（防止错误拆分）
            string[] idList = ids.Split(new[] { separator }, StringSplitOptions.None);
            // 验证路径有效性
            if (idList.Length == 0)
                throw new MyException("路径格式错误：空路径");

            int targetIdIndex = idList.Length - 1;
            JToken parentJToken = obj;

            // 逐级遍历路径
            for (int i = 0; i < targetIdIndex; i++)
            {
                string key = idList[i];

                // 处理 JObject 类型
                if (parentJToken is JObject jObj)
                {
                    if (!jObj.ContainsKey(key))
                        throw new MyException($"路径不存在：在层级 {i} 找不到键 '{key}'");
                    parentJToken = jObj[key];
                }
                // 处理 JArray 类型
                else if (parentJToken is JArray jArr)
                {
                    if (!int.TryParse(key, out int index))
                        throw new MyException($"数组索引格式错误：层级 {i} 的值 '{key}' 不是有效整数");

                    if (index < 0 || index >= jArr.Count)
                        throw new MyException($"数组越界：层级 {i} 索引 {index} 超出范围 [0-{jArr.Count - 1}]");

                    parentJToken = jArr[index];
                }
                // 处理意外类型
                else
                {
                    throw new MyException($"路径类型错误：层级 {i} 的节点不是对象或数组");
                }
            }

            // 处理最终目标键
            string targetKey = idList[targetIdIndex];
            if (parentJToken is JObject finalObj)
            {
                if (!finalObj.ContainsKey(targetKey))
                    throw new MyException($"目标键不存在：找不到最终键 '{targetKey}'");
                return (finalObj, targetKey);
            }
            else if (parentJToken is JArray finalArr)
            {
                if (!int.TryParse(targetKey, out int index))
                    throw new MyException($"最终数组索引格式错误：'{targetKey}' 不是有效整数");

                if (index < 0 || index >= finalArr.Count)
                    throw new MyException($"最终数组越界：索引 {index} 超出范围 [0-{finalArr.Count - 1}]");

                return (finalArr, targetKey);
            }

            throw new MyException($"最终节点类型错误：期望对象或数组，实际类型为 {parentJToken?.GetType().Name}");
        }


    }
}
